package com.ly.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ly.common.core.bean.R;
import com.ly.common.core.bean.vo.SysButtonVO;
import com.ly.common.core.constant.BaseConstant;
import com.ly.common.core.exception.ServiceException;
import com.ly.common.core.utils.BaseUtils;
import com.ly.system.mapper.SysPermissionMapper;
import com.ly.system.service.ISysPermissionDataRuleService;
import com.ly.system.service.ISysPermissionService;
import com.ly.system.service.ISysRoleIndexService;
import com.ly.system.service.ISysRolePermissionService;
import com.ly.system.system.bean.entity.SysPermission;
import com.ly.system.system.bean.entity.SysPermissionDataRule;
import com.ly.system.system.bean.entity.SysRoleIndex;
import com.ly.system.system.bean.entity.SysRolePermission;
import com.ly.system.system.bean.model.SysPermissionTree;
import com.ly.system.system.bean.vo.MenuVO;
import com.ly.system.system.bean.vo.SysPermissionVO;
import com.ly.system.util.TreeUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 菜单权限-服务
 *
 * @author jeecg
 * @since 2018-12-21
 */
@Service
@RequiredArgsConstructor
public class SysPermissionServiceImpl extends ServiceImpl<SysPermissionMapper, SysPermission> implements ISysPermissionService {

    private final SysPermissionMapper sysPermissionMapper;
    private final ISysPermissionDataRuleService permissionDataRuleService;
    private final ISysRoleIndexService sysRoleIndexService;
    private final ISysRolePermissionService sysRolePermissionService;

    @Override
    public R getList(SysPermission entity) {
        // List<SysPermission> list = this.list(
        //         new LambdaQueryWrapper<SysPermission>()
        //                 .eq(SysPermission::getDelFlag, BaseConstant.DEL_FLAG_0)
        //                 .like(StrUtil.isNotEmpty(entity.getName()), SysPermission::getName, entity.getName())
        //                 .like(StrUtil.isNotEmpty(entity.getUrl()), SysPermission::getUrl, entity.getUrl())
        //                 .like(StrUtil.isNotEmpty(entity.getComponent()), SysPermission::getComponent, entity.getComponent())
        //                 .orderByAsc(SysPermission::getSortNo)
        // );
        List<SysPermission> list = sysPermissionMapper.getList(entity);
        List<SysPermissionTree> treeList = new ArrayList<>();
        // 如果有菜单名查询条件，则平铺数据 不做上下级
        if (StrUtil.isNotEmpty(entity.getName()) || StrUtil.isNotEmpty(entity.getUrl()) || StrUtil.isNotEmpty(entity.getComponent())) {
            treeList = list.stream().map(e -> new SysPermissionTree(e.setLeaf(true))).collect(Collectors.toList());
        } else {
            getTreeList(treeList, list, null);
        }
        return R.ok(treeList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R add(SysPermission entity) {
        // 判断是否是一级菜单，是的话清空父菜单
        if (BaseConstant.MENU_TYPE_0.equals(entity.getMenuType())) {
            entity.setParentId("");
        }
        String pid = entity.getParentId();
        if (StrUtil.isNotEmpty(pid)) {
            // 设置父节点不为叶子节点
            sysPermissionMapper.setMenuLeaf(pid, 0);
        }
        entity.setLeaf(true);
        boolean flag = this.save(entity);
        return flag ? R.ok(true, "创建成功") : R.fail("创建失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R edit(SysPermission entity) {
        SysPermission p = this.getById(entity.getId());
        if (p == null) {
            return R.fail("未找到菜单信息");
        }
        // Step1.判断是否是一级菜单，是的话清空父菜单ID
        if (BaseConstant.MENU_TYPE_0.equals(entity.getMenuType())) {
            entity.setParentId("");
        }
        // 判断是否有下级菜单，无则设置为叶子节点
        Long count = this.count(
                new LambdaQueryWrapper<SysPermission>()
                        .eq(SysPermission::getParentId, entity.getId())
        );
        if (count == 0) {
            entity.setLeaf(true);
        }
        this.updateById(entity);
        if (StrUtil.isNotEmpty(p.getParentId())) {
            // 设置父节点不为叶子节点
            sysPermissionMapper.setMenuLeaf(p.getParentId(), 0);
        }
        // 同步更改默认菜单
        SysRoleIndex defIndexCfg = this.sysRoleIndexService.queryDefaultIndex("null");
        boolean isDefIndex = defIndexCfg.getUrl().equals(p.getUrl());
        if (isDefIndex) {
            SysRoleIndex index = BeanUtil.copyProperties(entity, SysRoleIndex.class);
            this.sysRoleIndexService.updateDefaultIndex(index);
        }
        boolean flag = this.updateById(entity);
        return flag ? R.ok(true, "修改成功") : R.fail("修改失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R delete(String id) {
        SysPermission sysPermission = this.getById(id);
        if (sysPermission == null) {
            return R.fail("未找到菜单信息");
        }
        String pid = sysPermission.getParentId();
        if (StrUtil.isNotEmpty(pid)) {
            // 兄弟节点个数，等于1则只有自己一个，大于1则表示有兄弟
            Long count = this.count(
                    new LambdaQueryWrapper<SysPermission>()
                            .eq(SysPermission::getParentId, pid)
            );
            if (count == 1) {
                // 若父节点无其他子节点，则该父节点是叶子节点
                sysPermissionMapper.setMenuLeaf(pid, 1);
            }
        }
        List<SysPermission> allList = this.list();
        List<SysPermission> childMenuList = TreeUtils.getChildMenuList(allList, id);
        List<String> idList = childMenuList.stream().map(n -> n.getId()).collect(Collectors.toList());
        idList.add(id);
        // 清空菜单权限规则
        permissionDataRuleService.remove(
                new LambdaQueryWrapper<SysPermissionDataRule>()
                        .in(SysPermissionDataRule::getPermissionId, idList)
        );
        // 删除角色授权表
        sysRolePermissionService.remove(
                new LambdaQueryWrapper<SysRolePermission>()
                        .in(SysRolePermission::getPermissionId, idList)
        );
        boolean flag = this.remove(
                new LambdaQueryWrapper<SysPermission>()
                        .in(SysPermission::getId, idList)
        );
        return flag ? R.ok(true, "删除成功") : R.fail("删除失败");
    }

    @Override
    public R getAuthByToken() {
        SysPermissionVO vo = new SysPermissionVO();
        //管理员全部权限
        List<SysPermission> allMenuList = this.baseMapper.getAuthByUserId(BaseUtils.checkIsAdmin() ? null : BaseUtils.getId());
        String indexUrl = sysRoleIndexService.getIndexUrlByUserName(BaseUtils.getId());
        // 如果没有授权角色首页，则自动添加首页路由
        if (CollUtil.isEmpty(allMenuList) || !allMenuList.stream().anyMatch(n -> indexUrl.equals(n.getUrl()))) {
            SysPermission indexMenu = this.getOne(
                    new LambdaQueryWrapper<SysPermission>()
                            .eq(SysPermission::getUrl, indexUrl)
            );
            if (indexMenu == null) {
                throw new ServiceException("默认首页路径url有错误，请检查！");
            }
            // 如果没有授权一级菜单，则自身变为一级菜单
            SysPermission finalIndexMenu = indexMenu;
            if (indexMenu.getParentId() != null && !allMenuList.stream().anyMatch(n -> finalIndexMenu.getParentId().equals(n.getId()))) {
                indexMenu.setMenuType(0);
                indexMenu.setParentId("");
            }
            if (StrUtil.isEmpty(indexMenu.getIcon())) {
                indexMenu.setIcon("ant-design:home");
            }
            allMenuList.add(0, indexMenu);
        }
        // 按钮权限
        List<SysButtonVO> buttonList = allMenuList.stream()
                .filter(n -> BaseConstant.MENU_TYPE_2.equals(n.getMenuType())
                        && BaseConstant.STATUS_1.equals(n.getStatus()))
                .map(n -> new SysButtonVO(n.getPerms(), n.getPermsType(), n.getName(), BaseConstant.STATUS_1))
                .collect(Collectors.toList());
        List<String> buttonVoCodeList = buttonList.stream().map(n -> n.getAction()).collect(Collectors.toList());
        // 所有的按钮权限
        List<SysPermission> allButtonList = this.list(
                new LambdaQueryWrapper<SysPermission>()
                        .select(SysPermission::getName, SysPermission::getPermsType, SysPermission::getPerms, SysPermission::getStatus)
                        .eq(SysPermission::getMenuType, BaseConstant.MENU_TYPE_2)
                // .eq(SysPermission::getStatus, "1")
        );
        List<SysButtonVO> allButtonVoList = allButtonList.stream()
                .map(n -> new SysButtonVO(n.getPerms(), n.getPermsType(), n.getName(), n.getStatus()))
                .collect(Collectors.toList());
        List<MenuVO> treeDto = allMenuList.stream()
                .filter(n -> BaseConstant.MENU_TYPE_0.equals(n.getMenuType()) || BaseConstant.MENU_TYPE_1.equals(n.getMenuType()))
                .map(n -> new MenuVO(n)).collect(Collectors.toList());
        vo.setMenu(TreeUtils.getMenuTreeListByMap(treeDto));
        vo.setButton(buttonList);
        vo.setButtonCodeList(buttonVoCodeList);
        vo.setAllButton(allButtonVoList);
        vo.setSysSafeMode(false);
        return R.ok(vo);
    }

    @Override
    public R getMenuListByParent(String parentId) {
        List<SysPermissionTree> vos = new ArrayList<>();
        List<SysPermission> list = new ArrayList<>();
        if (StrUtil.isEmpty(parentId)) {
            list = this.list(
                    new LambdaQueryWrapper<SysPermission>()
                            .eq(SysPermission::getMenuType, BaseConstant.MENU_TYPE_0)
                            .orderByAsc(SysPermission::getSortNo)
            );
        } else {
            list = this.list(
                    new LambdaQueryWrapper<SysPermission>()
                            .eq(SysPermission::getParentId, parentId)
                            .orderByAsc(SysPermission::getSortNo)
            );
        }
        list.stream().forEach(n -> vos.add(new SysPermissionTree(n)));
        return R.ok(vos);
    }

    /**
     * 树形菜单封装
     *
     * @param treeList
     * @param metaList
     * @param temp
     */
    private void getTreeList(List<SysPermissionTree> treeList, List<SysPermission> metaList, SysPermissionTree temp) {
        for (SysPermission permission : metaList) {
            String tempPid = permission.getParentId();
            SysPermissionTree tree = new SysPermissionTree(permission);
            if (temp == null && StrUtil.isEmpty(tempPid)) {
                treeList.add(tree);
                if (ObjUtil.notEqual(tree.getIsLeaf(), true)) {
                    getTreeList(treeList, metaList, tree);
                }
            } else if (temp != null && tempPid != null && tempPid.equals(temp.getId())) {
                temp.getChildren().add(tree);
                if (ObjUtil.notEqual(tree.getIsLeaf(), true)) {
                    getTreeList(treeList, metaList, tree);
                }
            }
        }
    }

    @Override
    public boolean checkAuthUrlPath(SysPermission entity) {
        long count = this.count(
                new LambdaQueryWrapper<SysPermission>()
                        .eq(SysPermission::getUrl, entity.getUrl())
                        .ne(StrUtil.isNotEmpty(entity.getId()), SysPermission::getId, entity.getId())
                        .eq(SysPermission::getAlwaysShow, entity.getAlwaysShow())
        );
        return count == 0;
    }
}
